home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 21 / CU Amiga Magazine's Super CD-ROM 21 (1998)(EMAP Images)(GB)[!][issue 1998-04].iso / CUCD / Programming / Python-1.4 / Python1.4_Source / Modules / arexxmodule.c < prev    next >
C/C++ Source or Header  |  1997-01-01  |  20KB  |  899 lines

  1.  
  2. /********************************************************************
  3.  
  4.     Lowlevel Amiga ARexx module.
  5.  
  6.     Provides `arexxport' object, which is a opened ARexx port.
  7.     The port returns `arexxmsg' objects.
  8.  
  9. -----------------------------------------------
  10.     (c) 1996 Irmen de Jong.
  11.  
  12.     History:
  13.  
  14.     20-may-96   Created.
  15.     25-may-96   Major overhaul; now uses arexxmsg objects.
  16.     27-may-96   Added ReadArgs function.
  17.      8-jun-96   Rewrote ReadArgs.
  18.      9-jun-96   Moved ReadArgs to doslibmodule.
  19.     26-aug-96   Added message.getvar().
  20.  
  21. Module members:
  22.  
  23.     error       -- Exeption string object.  ('arexx.error')
  24.     port        -- function returning a new ARexx port object.
  25.                    port = arexxll.port('PORTNAME')
  26.     errorstring -- returns string associated with arexx error code.
  27.  
  28. ARexxPort object members:
  29.  
  30.     name        -- attribute, name of the port (RO)
  31.     signal      -- attribute, signal mask of the MsgPort's sigbit (RO)
  32.     close       -- function, closes the port
  33.     wait        -- function, waits for message to arrive
  34.     getmsg      -- function, returns ARexxMessage object, or None.
  35.     send        -- function, to send command to other port
  36.                    send(to,cmd,async?)    returns (rc,rc2,result) if synchronous.
  37.  
  38. ARexxMessage object members:
  39.  
  40.     reply       -- function, replies the message with the given results
  41.                    Each message must be replied to!
  42.     setvar      -- function, sets ARexx variable
  43.     getvar      -- function, extracts ARexx variable
  44.     wantresult  -- attribute, does the message require a result string? (BOOL, RO)
  45.     msg         -- attribute, the message itself (string) (RO)
  46.     rc          -- attribute, result code for reply() (integer)
  47.     rc2         -- attribute, secondary result code (string or None)
  48.     result      -- attribute, result string (string or None)
  49.  
  50.  
  51. **************************************************************************/
  52.  
  53. #include <stdlib.h>
  54. #include <dos.h>
  55. #include <exec/types.h>
  56. #include <exec/memory.h>
  57. #include <dos/dos.h>
  58. #include <exec/libraries.h>
  59. #include <rexx/storage.h>
  60. #include <rexx/rxslib.h>
  61. #include <proto/dos.h>
  62. #include <proto/exec.h>
  63. #include <proto/rexxsyslib.h>
  64. #include <clib/alib_protos.h>
  65. #include "allobjects.h"
  66. #include "modsupport.h"
  67.  
  68. #define ARB_HF_CMDSHELL    (1L << 0)
  69. #define ARB_HF_USRMSGPORT  (1L << 1)
  70. #define ARB_HF_NOTPUBLIC   (1L << 2)
  71.  
  72. #define toupper(c) (c&(~32))
  73.  
  74. struct RexxHost
  75. {
  76.     struct MsgPort *port;
  77.     char portname[ 80 ];
  78.     long replies;
  79.     long flags;
  80.     APTR userdata;
  81. };
  82.  
  83. typedef struct {
  84.     PyObject_HEAD
  85.     struct RexxHost *host;
  86.     ULONG signal;
  87. } arexxportobject;
  88.  
  89. typedef struct {
  90.     PyObject_HEAD
  91.     struct RexxMsg *msg;
  92.     BOOL replied;           // has this message been replied to yet?
  93.     int rc;                 // primary return code (RC -- int)
  94.     PyObject *rc2;          // secondary return code (RC2 -- string)
  95.     PyObject *result;       // RESULT string
  96. } arexxmsgobject;
  97.  
  98.  
  99. struct ExecBase *AbsExecBase;
  100.  
  101. static PyObject *error;    // Exception
  102.  
  103. /* Prototypes for functions defined in arexxmodule.c */
  104.  
  105. struct RexxMsg *CreateRexxCommand( struct RexxHost *host, char *buff, BPTR fh );
  106. static void ReplyRexxCommand( struct RexxMsg *rxmsg, long prim, long sec, char *res );
  107. static void FreeRexxCommand( struct RexxMsg *rxmsg );
  108. static void CloseDownARexxHost( struct RexxHost *host );
  109. static struct RexxHost *SetupARexxHost( char *basename);
  110. static struct RexxMsg *GetARexxMsg( struct RexxHost *host );
  111. struct RexxMsg *SendRexxCommandToPort( struct RexxHost *host,
  112.         char *port, char *cmd, BPTR fh );
  113.  
  114. static BOOL Test_Open(arexxportobject * );
  115. static BOOL Test_Replied(arexxmsgobject * );
  116. static PyObject * port_close(arexxportobject * , PyObject * );
  117. static PyObject * port_wait(arexxportobject * , PyObject * );
  118. static PyObject * port_getmsg(arexxportobject * , PyObject * );
  119. static void port_dealloc(arexxportobject * );
  120. static PyObject * port_getattr(arexxportobject * , unsigned char * );
  121. static PyObject * port_repr(arexxportobject * );
  122. static PyObject * newarexxportobject(unsigned char * );
  123. static void msg_dealloc(arexxmsgobject * );
  124. static PyObject * msg_getattr(arexxmsgobject * , unsigned char * );
  125. static PyObject * msg_repr(arexxmsgobject * );
  126. static PyObject * newarexxmsgobject(struct RexxMsg * );
  127. static PyObject * ARexx_openport(PyObject * , PyObject * );
  128.  
  129.  
  130. ///*** AREXXPORT OBJECT MEMBER FUNCTIONS ***/
  131.  
  132. static BOOL Test_Open(arexxportobject *ao)
  133. {
  134.     if(ao->host) return TRUE;
  135.     PyErr_SetString(error,"closed port");
  136.     return FALSE;
  137. }
  138.  
  139. static PyObject *port_close(arexxportobject *ao, PyObject *args)
  140. {
  141.     if(!PyArg_NoArgs(args)) return NULL;
  142.  
  143.     if(ao->host) CloseDownARexxHost(ao->host);
  144.     ao->host=NULL;
  145.     Py_INCREF(Py_None);
  146.     return Py_None;
  147. }
  148.  
  149. static PyObject *port_wait(arexxportobject *ao, PyObject *args)
  150. {
  151.     if(!PyArg_NoArgs(args)) return NULL;
  152.  
  153.     if(Test_Open(ao))
  154.     {
  155.         ULONG sigs = Wait(ao->signal | SIGBREAKF_CTRL_C);   /* XXX Abort with ^C */
  156.         if(sigs & SIGBREAKF_CTRL_C)
  157.         {
  158.             PyErr_SetNone(KeyboardInterrupt);
  159.             return NULL;
  160.         }
  161.  
  162.         Py_INCREF(Py_None);
  163.         return Py_None;
  164.     } else return NULL;
  165. }
  166.  
  167. static PyObject *port_getmsg(arexxportobject *ao, PyObject *args)
  168. {
  169.     if(!PyArg_NoArgs(args)) return NULL;
  170.  
  171.     if(Test_Open(ao))
  172.     {
  173.         struct RexxMsg *msg;
  174.  
  175.         if(msg=GetARexxMsg(ao->host))
  176.         {
  177.             return newarexxmsgobject(msg);
  178.         }
  179.  
  180.         Py_INCREF(Py_None);
  181.         return Py_None;
  182.     } else return NULL;
  183. }
  184.  
  185. static PyObject *port_send(arexxportobject *ao, PyObject *args)
  186. {
  187.     char *to;
  188.     char *cmd;
  189.     long async;
  190.  
  191.     if(!PyArg_ParseTuple(args,"ssi",&to,&cmd,&async)) return NULL;
  192.     if(Test_Open(ao))
  193.     {
  194.         struct RexxMsg *sentrm;
  195.         if( !(sentrm = SendRexxCommandToPort(ao->host, to, cmd,NULL)))
  196.         {
  197.             PyErr_SetString(error,"can't send to port");
  198.             return NULL;
  199.         }
  200.         if(!async)
  201.         {
  202.             /* wait for the reply */
  203.             PyObject *reso = NULL;
  204.             long rc;
  205.             struct RexxMsg *rm;
  206.             BOOL waiting = TRUE;
  207.             
  208.             do
  209.             {
  210.                 WaitPort( ao->host->port );
  211.                     
  212.                 while( rm = (struct RexxMsg *) GetMsg(ao->host->port) )
  213.                 {
  214.                     /* Reply? */
  215.                     if( rm->rm_Node.mn_Node.ln_Type == NT_REPLYMSG )
  216.                     {
  217.                         /* 'unsere' Msg? */
  218.                         if( rm == sentrm )
  219.                         {
  220.                             rc = rm->rm_Result1;
  221.                                 
  222.                             if( !rc && rm->rm_Result2 )
  223.                             {
  224.                                 /* Res2 is String */
  225.                                 reso = Py_BuildValue("(iss)",rc,NULL,rm->rm_Result2);
  226.                             }
  227.                             else
  228.                             {
  229.                                 /* Res2 is number */
  230.                                 reso = Py_BuildValue("(iis)",rc,rm->rm_Result2,NULL);
  231.                             }
  232.  
  233.                             waiting = FALSE;
  234.                         }
  235.                             
  236.                         FreeRexxCommand( rm );
  237.                         --ao->host->replies;
  238.                     }
  239.                         
  240.                     /* sonst Kommando -> Fehler */
  241.                     else if( ARG0(rm) )
  242.                     {
  243.                         ReplyRexxCommand( rm, -20, (long)
  244.                             "invalid port", NULL );
  245.                     }
  246.                 }
  247.             }
  248.             while( waiting );
  249.  
  250.             return reso;
  251.         }
  252.         else
  253.         {
  254.             Py_INCREF(Py_None);
  255.             return Py_None;
  256.         }
  257.     } else return NULL;
  258. }
  259.  
  260.  
  261. static struct methodlist port_methods[] = {
  262.     {"close", (method)port_close, 0},
  263.     {"getmsg", (method)port_getmsg, 0},
  264.     {"wait", (method)port_wait, 0},
  265.     {"send", (method)port_send, 1},
  266.     {NULL,      NULL}       /* sentinel */
  267. };
  268.  
  269.  
  270. static void
  271. port_dealloc(arexxportobject *self)         // `destructor'
  272. {
  273.     if(self->host) CloseDownARexxHost(self->host);
  274.     PyMem_DEL(self);
  275. }
  276.  
  277. static PyObject *
  278. port_getattr(arexxportobject *ao, char *name)
  279. {
  280.     if(ao->host)
  281.     {
  282.         if (strcmp(name, "name")==0)
  283.         {
  284.             if(ao->host->flags & ARB_HF_NOTPUBLIC)
  285.             {
  286.                 // A non-public port doesn't have a name!
  287.                 PyErr_SetString(AttributeError,name); return NULL;
  288.             }   
  289.             return PyString_FromString(ao->host->portname);
  290.         }
  291.         else if(strcmp(name,"signal")==0)
  292.             return PyInt_FromLong(ao->signal);
  293.     }
  294.     return Py_FindMethod(port_methods, (PyObject *)ao, name);
  295. }
  296.  
  297. static PyObject *
  298. port_repr(arexxportobject *ao)
  299. {
  300.     char buf[200];
  301.     char *w;
  302.  
  303.     if(!(ao->host))
  304.         w="(closed)";
  305.     else if(ao->host->flags & ARB_HF_NOTPUBLIC)
  306.         w="(private)";
  307.     else
  308.         w=ao->host->portname;
  309.     sprintf(buf,"<arexx port %s at %lx>",w,(long)ao);
  310.     return PyString_FromString(buf);
  311. }
  312.  
  313. static typeobject ARexxPorttype = {
  314.     OB_HEAD_INIT(&Typetype)
  315.     0,          /*ob_size*/
  316.     "arexxport",        /*tp_name*/
  317.     sizeof(arexxportobject),    /*tp_size*/
  318.     0,          /*tp_itemsize*/
  319.     /* methods */
  320.     (destructor)port_dealloc, /*tp_dealloc*/
  321.     0,          /*tp_print*/
  322.     (getattrfunc)port_getattr, /*tp_getattr*/
  323.     (setattrfunc)0, /*tp_setattr*/
  324.     0,          /*tp_compare*/
  325.     (reprfunc)port_repr,        /*tp_repr*/
  326. };
  327.  
  328.  
  329. static PyObject *
  330. newarexxportobject(char *name)              // `constructor'
  331. {
  332.     arexxportobject *ao;
  333.  
  334.     if(name)
  335.     {
  336.         if(strlen(name)<2)
  337.         {
  338.             PyErr_SetString(ValueError,"port name too short");
  339.             return NULL;
  340.         }
  341.  
  342.         (void)strupr(name);
  343.     }
  344.  
  345.     if(ao = PyObject_NEW(arexxportobject, &ARexxPorttype))
  346.     {
  347.         if(ao->host=SetupARexxHost(name))
  348.         {
  349.             ao->signal = 1<<ao->host->port->mp_SigBit;
  350.             return (PyObject*)ao;
  351.         }
  352.         else PyErr_SetString(error,"can't open port");
  353.  
  354.         PyMem_DEL(ao); ao=NULL;
  355.     }
  356.     return (PyObject*)ao;
  357. }
  358.  
  359.  
  360. ///
  361.  
  362. ///*** AREXXMSG OBJECT MEMBER FUNCTIONS ***/
  363.  
  364. static BOOL Test_Replied(arexxmsgobject *am)
  365. {
  366.     if(am->replied)
  367.     {
  368.         PyErr_SetString(error,"already replied");
  369.         return FALSE;
  370.     }
  371.     return TRUE;
  372. }
  373.  
  374. static PyObject *msg_reply(arexxmsgobject *am, PyObject *args)
  375. {
  376.     if(!PyArg_NoArgs(args)) return NULL;
  377.  
  378.     if(Test_Replied(am))
  379.     {
  380.         char *rc2, *result;
  381.  
  382.         rc2 = PyString_Check(am->rc2)? PyString_AsString(am->rc2) : NULL;
  383.         result = PyString_Check(am->result)? PyString_AsString(am->result) : NULL;
  384.  
  385.         am->rc = -am->rc;       // for ReplyRexxCommand; 'rc2 is string'
  386.         ReplyRexxCommand(am->msg,am->rc,(long)rc2,result);
  387.         am->replied=TRUE;
  388.  
  389.         Py_INCREF(Py_None);
  390.         return Py_None;
  391.     } else return NULL;
  392. }
  393.  
  394. static PyObject *msg_setvar(arexxmsgobject *am, PyObject *args)
  395. {
  396.     char *name, *val;
  397.     int vlen;
  398.     if(!PyArg_ParseTuple(args,"ss#",&name,&val,&vlen)) return NULL;
  399.  
  400.     if(Test_Replied(am))
  401.     {
  402.         if(0==SetRexxVar((struct Message*)am->msg,name,val,vlen))
  403.         {
  404.             Py_INCREF(Py_None);
  405.             return Py_None;
  406.         }
  407.         else PyErr_SetString(error,"can't set var");
  408.     }
  409.     return NULL;
  410. }
  411.  
  412. static PyObject *msg_getvar(arexxmsgobject *am, PyObject *args)
  413. {
  414.     char *name, *val;
  415.     if(!PyArg_ParseTuple(args,"s",&name)) return NULL;
  416.  
  417.     if(Test_Replied(am))
  418.     {
  419.         if(0==GetRexxVar((struct Message*)am->msg,name,&val))
  420.         {
  421.             if(val!=NULL) return PyString_FromString(val);
  422.         }
  423.  
  424.         PyErr_SetString(error,"can't get var");
  425.     }
  426.     return NULL;
  427. }
  428.  
  429. static struct methodlist msg_methods[] = {
  430.     {"reply", (method) msg_reply, 0},
  431.     {"setvar", (method) msg_setvar, 1},
  432.     {"getvar", (method) msg_getvar, 1},
  433.     {NULL,      NULL}       /* sentinel */
  434. };
  435.  
  436. static void
  437. msg_dealloc(arexxmsgobject *am)         // `destructor'
  438. {   
  439.     if(!am->replied)
  440.     {
  441.         char *rc2, *result;
  442.  
  443.         rc2 = PyString_Check(am->rc2)? PyString_AsString(am->rc2) : NULL;
  444.         result = PyString_Check(am->result)? PyString_AsString(am->result) : NULL;
  445.  
  446.         am->rc = -am->rc;       // for ReplyRexxCommand; 'rc2 is string'
  447.         ReplyRexxCommand(am->msg,am->rc,(long)rc2,result);
  448.     }
  449.     Py_DECREF(am->rc2);
  450.     Py_DECREF(am->result);
  451.     PyMem_DEL(am);
  452. }
  453.  
  454.  
  455. static PyObject *
  456. msg_getattr(arexxmsgobject *am, char *name)
  457. {
  458.     if (strcmp(name, "msg")==0)
  459.         return PyString_FromString(ARG0(am->msg));
  460.     if (strcmp(name, "rc")==0)
  461.         return PyInt_FromLong(am->rc);
  462.     if (strcmp(name, "rc2")==0)
  463.     {
  464.         Py_INCREF(am->rc2);
  465.         return am->rc2;
  466.     }
  467.     if (strcmp(name, "result")==0)
  468.     {
  469.         Py_INCREF(am->result);
  470.         return am->result;
  471.     }
  472.     if (strcmp(name, "wantresult")==0)
  473.     {
  474.         if( am->msg->rm_Action & RXFF_RESULT )
  475.             return PyInt_FromLong(1);
  476.         else
  477.             return PyInt_FromLong(0);
  478.     }
  479.  
  480.     return Py_FindMethod(msg_methods, (PyObject *)am, name);
  481. }
  482.  
  483. static int
  484. msg_setattr(arexxmsgobject *am, char *name, PyObject *args)
  485. {
  486.     if(args==NULL)
  487.     {
  488.         PyErr_SetString(AttributeError,"can't delete msg attrs"); return -1;
  489.     }
  490.  
  491.     if (strcmp(name, "rc")==0)
  492.     {
  493.         if(PyInt_Check(args))
  494.         {
  495.             long rc = PyInt_AsLong(args);
  496.             if(rc>=0)
  497.             {
  498.                 am->rc=rc;
  499.             }
  500.             else
  501.             {
  502.                 PyErr_SetString(ValueError,"rc must be >=0"); return -1;
  503.             }
  504.         }
  505.         else
  506.         {
  507.             PyErr_SetString(TypeError,"expecting int arg"); return -1;
  508.         }
  509.     }
  510.     else if (strcmp(name, "rc2")==0)
  511.     {
  512.         if(PyString_Check(args))
  513.         {
  514.             Py_DECREF(am->rc2);
  515.             Py_INCREF(args);
  516.             am->rc2 = args;
  517.         }
  518.         else
  519.         {
  520.             PyErr_SetString(TypeError,"expecting string arg"); return -1;
  521.         }
  522.     }
  523.     else if (strcmp(name, "result")==0)
  524.     {
  525.         if(PyString_Check(args))
  526.         {
  527.             Py_DECREF(am->result);
  528.             Py_INCREF(args);
  529.             am->result = args;
  530.         }
  531.         else
  532.         {
  533.             PyErr_SetString(TypeError,"expecting string arg"); return -1;
  534.         }
  535.     }
  536.     else
  537.     {
  538.         PyErr_SetString(AttributeError,name); return -1;
  539.     }
  540.  
  541.     return 0;
  542. }
  543.  
  544. static PyObject *
  545. msg_repr(arexxmsgobject *am)
  546. {
  547.     char buf[100];
  548.     sprintf(buf, "<arexx msg at %lx>", (long)am);
  549.     return PyString_FromString(buf);
  550. }
  551.  
  552. static typeobject ARexxMsgtype = {
  553.     OB_HEAD_INIT(&Typetype)
  554.     0,          /*ob_size*/
  555.     "arexxmsg",        /*tp_name*/
  556.     sizeof(arexxmsgobject),    /*tp_size*/
  557.     0,          /*tp_itemsize*/
  558.     /* methods */
  559.     (destructor)msg_dealloc, /*tp_dealloc*/
  560.     0,          /*tp_print*/
  561.     (getattrfunc)msg_getattr, /*tp_getattr*/
  562.     (setattrfunc)msg_setattr, /*tp_setattr*/
  563.     0,          /*tp_compare*/
  564.     (reprfunc)msg_repr,        /*tp_repr*/
  565. };
  566.  
  567. static PyObject *
  568. newarexxmsgobject(struct RexxMsg *msg)             // `constructor'
  569. {
  570.     arexxmsgobject *am;
  571.  
  572.     if(am = PyObject_NEW(arexxmsgobject, &ARexxMsgtype))
  573.     {
  574.         am->msg=msg;
  575.         am->rc=0;
  576.         Py_INCREF(Py_None); am->rc2=Py_None;
  577.         Py_INCREF(Py_None); am->result=Py_None;
  578.         am->replied=FALSE;
  579.     }
  580.     return (PyObject*)am;
  581. }
  582.  
  583.  
  584. ///
  585.  
  586. ///******************************* AREXX SUPPORT FUNCTIONS *******************/
  587.  
  588. struct RexxMsg *CreateRexxCommand( struct RexxHost *host, char *buff, BPTR fh )
  589. {
  590.     struct RexxMsg *rexx_command_message;
  591.  
  592.     if( (rexx_command_message = CreateRexxMsg( host->port,
  593.         "python", host->port->mp_Node.ln_Name)) == NULL )
  594.     {
  595.         return( NULL );
  596.     }
  597.  
  598.     if( (rexx_command_message->rm_Args[0] =
  599.         CreateArgstring(buff,strlen(buff))) == NULL )
  600.     {
  601.         DeleteRexxMsg(rexx_command_message);
  602.         return( NULL );
  603.     }
  604.  
  605.     rexx_command_message->rm_Action = RXCOMM | RXFF_RESULT;
  606.     rexx_command_message->rm_Stdin  = fh;
  607.     rexx_command_message->rm_Stdout = fh;
  608.     
  609.     return( rexx_command_message );
  610. }
  611.  
  612.  
  613. static void ReplyRexxCommand(
  614.     struct RexxMsg  *rexxmessage,
  615.     long            primary,
  616.     long            secondary,
  617.     char            *result )
  618. {
  619.     if( rexxmessage->rm_Action & RXFF_RESULT )
  620.     {
  621.         if( primary == 0 )
  622.         {
  623.             secondary = result
  624.                 ? (long) CreateArgstring( result, strlen(result) )
  625.                 : (long) NULL;
  626.         }
  627.         else
  628.         {
  629.             char buf[16];
  630.             
  631.             if( primary > 0 )
  632.             {
  633.                 sprintf( buf, "%ld", secondary );
  634.                 result = buf;
  635.             }
  636.             else
  637.             {
  638.                 primary = -primary;
  639.                 result = (char *) secondary;
  640.             }
  641.             
  642.             SetRexxVar( (struct Message *) rexxmessage,
  643.                 "RC2", result, strlen(result) );
  644.             
  645.             secondary = 0;
  646.         }
  647.     }
  648.     else if( primary < 0 )
  649.         primary = -primary;
  650.     
  651.     rexxmessage->rm_Result1 = primary;
  652.     rexxmessage->rm_Result2 = secondary;
  653.     ReplyMsg( (struct Message *) rexxmessage );
  654. }
  655.  
  656. static void FreeRexxCommand( struct RexxMsg *rexxmessage )
  657. {
  658.     if( !rexxmessage->rm_Result1 && rexxmessage->rm_Result2 )
  659.         DeleteArgstring( (char *) rexxmessage->rm_Result2 );
  660.  
  661.     if( rexxmessage->rm_Stdin &&
  662.         rexxmessage->rm_Stdin != Input() )
  663.         Close( rexxmessage->rm_Stdin );
  664.  
  665.     if( rexxmessage->rm_Stdout &&
  666.         rexxmessage->rm_Stdout != rexxmessage->rm_Stdin &&
  667.         rexxmessage->rm_Stdout != Output() )
  668.         Close( rexxmessage->rm_Stdout );
  669.  
  670.     DeleteArgstring( (char *) ARG0(rexxmessage) );
  671.     DeleteRexxMsg( rexxmessage );
  672. }
  673.  
  674.  
  675. static void CloseDownARexxHost( struct RexxHost *host )
  676. {
  677.     struct RexxMsg *rexxmsg;
  678.     
  679.     if( host->port )
  680.     {
  681.         /* Port abmelden */
  682.         if(!(host->flags & ARB_HF_NOTPUBLIC))
  683.             RemPort( host->port );
  684.         
  685.         /* Auf noch ausstehende Replies warten */
  686.         while( host->replies > 0 )
  687.         {
  688.             WaitPort( host->port );
  689.             
  690.             while( rexxmsg = (struct RexxMsg *) GetMsg(host->port) )
  691.             {
  692.                 if( rexxmsg->rm_Node.mn_Node.ln_Type == NT_REPLYMSG )
  693.                 {
  694.                     FreeRexxCommand( rexxmsg );
  695.                     --host->replies;
  696.                 }
  697.                 else
  698.                     ReplyRexxCommand( rexxmsg, -20, (long) "Host closing down", NULL );
  699.             }
  700.         }
  701.         
  702.         /* MsgPort leeren */
  703.         while( rexxmsg = (struct RexxMsg *) GetMsg(host->port) )
  704.             ReplyRexxCommand( rexxmsg, -20, (long) "Host closing down", NULL );
  705.         
  706. //        if( !(host->flags & ARB_HF_USRMSGPORT) )
  707.             DeleteMsgPort( host->port );
  708.     }
  709.     
  710.     free( host );
  711. }
  712.  
  713. // static struct RexxHost *SetupARexxHost( char *basename, struct MsgPort *usrport )
  714. static struct RexxHost *SetupARexxHost( char *basename)
  715. {
  716.     struct RexxHost *host;
  717.     int ext = 0;
  718.     
  719.     if( !(host = calloc(sizeof *host, 1)) )
  720.         return NULL;
  721.  
  722.     if(basename) strcpy( host->portname, basename );
  723.     else host->flags |= ARB_HF_NOTPUBLIC;
  724.  
  725.     if( !(host->port = CreateMsgPort()) )
  726.     {
  727.         free( host );
  728.         return NULL;
  729.     }
  730.     else
  731.     {
  732.         host->port->mp_Node.ln_Pri = 0;
  733.     }
  734.     
  735.  
  736.     if(!(host->flags & ARB_HF_NOTPUBLIC))
  737.     {
  738.         Forbid();
  739.         while( FindPort(host->portname) )
  740.             sprintf( host->portname, "%s.%d", basename, ++ext );
  741.  
  742.         host->port->mp_Node.ln_Name = host->portname;
  743.         AddPort( host->port );
  744.  
  745.         Permit();
  746.     }
  747.     
  748.     return( host );
  749. }
  750.  
  751. /* GetARexxMsg:
  752. ** returns the RexxMsg that is waiting at the port, 
  753. ** or NULL if no message is present. 
  754. */
  755. static struct RexxMsg *GetARexxMsg( struct RexxHost *host )
  756. {
  757.     struct RexxMsg *rexxmsg;
  758.  
  759.     while( rexxmsg = (struct RexxMsg *) GetMsg(host->port) )
  760.     {
  761.         if( (rexxmsg->rm_Action & RXCODEMASK) != RXCOMM )
  762.         {
  763.             /* Keine Rexx-Message */
  764.             ReplyMsg( (struct Message *) rexxmsg );
  765.         }
  766.         else if( rexxmsg->rm_Node.mn_Node.ln_Type == NT_REPLYMSG )
  767.         {
  768.             struct RexxMsg *org = (struct RexxMsg *) rexxmsg->rm_Args[15];
  769.             
  770.             if( org )
  771.             {
  772.                 /* Reply zu durchgereichter Msg */
  773.                 if( rexxmsg->rm_Result1 != 0 )
  774.                 {
  775.                     /* Befehl unbekannt */
  776.                     ReplyRexxCommand( org, 20, ERROR_NOT_IMPLEMENTED, NULL );
  777.                 }
  778.                 else
  779.                 {
  780.                     ReplyRexxCommand( org, 0, 0, (char *) rexxmsg->rm_Result2 );
  781.                 }
  782.             }
  783.  
  784.             FreeRexxCommand( rexxmsg );
  785.             --host->replies;
  786.         }
  787.         else if( ARG0(rexxmsg) )
  788.         {
  789.             return rexxmsg;     /* return the ARexx message! */
  790.         }
  791.         else
  792.         {
  793.             ReplyMsg( (struct Message *) rexxmsg );
  794.         }
  795.     }
  796.  
  797.     return NULL;    /* no important message arrived. */
  798. }
  799.  
  800.  
  801. struct RexxMsg *SendRexxCommandToPort( struct RexxHost *host, char *port, char *cmd, BPTR fh )
  802. {
  803.     struct RexxMsg *rcm;
  804.     
  805.     if( rcm = CreateRexxCommand(host, cmd, fh) )
  806.     {
  807.         struct MsgPort *rexxport;
  808.     
  809.         Forbid();
  810.  
  811.         if( (rexxport = FindPort(port)) == NULL )
  812.         {
  813.             Permit();
  814.             return( NULL );
  815.         }
  816.  
  817.         PutMsg( rexxport, &rcm->rm_Node );
  818.     
  819.         Permit();
  820.     
  821.         ++host->replies;
  822.         return( rcm );
  823.     }
  824.     else
  825.         return NULL;
  826. }
  827.  
  828. ///
  829.  
  830. ///******************************** MODULE FUNCTIONS ************************/
  831.  
  832. static PyObject *
  833. ARexx_openport(PyObject *self, PyObject *args)
  834. {
  835.     PyObject *p=NULL;
  836.     
  837.     if (!PyArg_ParseTuple(args, "|O", &p))
  838.         return NULL;
  839.  
  840.     if(!p)
  841.         return newarexxportobject("PYTHON");
  842.     else if(p==Py_None)
  843.         /* open anonymous port (only for sending) */
  844.         return newarexxportobject(NULL);
  845.     else if(PyString_Check(p))
  846.         return newarexxportobject(PyString_AsString(p));
  847.     else
  848.         return (PyObject*)PyErr_BadArgument();
  849. }
  850.  
  851.  
  852. static PyObject *
  853. ARexx_errorstring(PyObject *self, PyObject *args)
  854. {
  855. /* undocumented function: */
  856. extern BOOL ErrorMsg(LONG err);
  857. #pragma libcall RexxSysBase ErrorMsg 60 001 
  858.  
  859.     long err;
  860.     if (!PyArg_ParseTuple(args, "i", &err))
  861.         return NULL;
  862.  
  863.     if(ErrorMsg(err))
  864.     {
  865.         struct NexxStr *s = (struct NexxStr*)getreg(REG_A0);
  866.         return PyString_FromStringAndSize(&s->ns_Buff[0],s->ns_Length);
  867.     }
  868.     else
  869.     {
  870.         PyErr_SetString(ValueError,"invalid error code");
  871.         return NULL;
  872.     }
  873. }
  874.  
  875.  
  876. /*** FUNCTIONS FROM THE MODULE ***/
  877.  
  878. static struct methodlist ARexx_global_methods[] = {
  879.     {"port",  ARexx_openport, 1},
  880.     {"errorstring", ARexx_errorstring, 1},
  881.     {NULL,      NULL}       /* sentinel */
  882. };
  883. ///
  884.  
  885. void
  886. initarexx Py_PROTO((void))
  887. {
  888.     PyObject *m, *d;
  889.         AbsExecBase = *(struct ExecBase**)4;
  890.  
  891.     m = Py_InitModule("arexxll", ARexx_global_methods);
  892.     d = PyModule_GetDict(m);
  893.  
  894.     /* Initialize error exception */
  895.     error = PyString_FromString("arexx.error");
  896.     if (error == NULL || PyDict_SetItemString(d, "error", error) != 0)
  897.         Py_FatalError("can't define arexxll.error");
  898. }
  899.